<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import {Bar_Type, DefaultsSenderCallbackRouter, DefaultsSenderRemote, PortRemote, Service_BazOptions, ServiceReceiver, ServiceRemote, TWELVE} from '/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.m.js';
import {Shape} from '/gen/mojo/public/interfaces/bindings/tests/sample_import.mojom.m.js';
import {Color} from '/gen/mojo/public/interfaces/bindings/tests/sample_import2.mojom.m.js';

// Checks that optional fields are passed with default values if we don't set
// them.
promise_test(async () => {
  const sender = new DefaultsSenderRemote();
  const router = new DefaultsSenderCallbackRouter();
  router.$.bindHandle(sender.$.bindNewPipeAndPassReceiver().handle);

  const waitForBar = new Promise(
      resolve => router.sendBar.addListener(resolve));
  sender.sendBar({});
  const bar = await waitForBar;
  assert_equals(bar.alpha, 255);
  assert_equals(bar.type, Bar_Type.VERTICAL);

  const waitForFoo = new Promise(
      resolve => router.sendFoo.addListener(resolve));
  sender.sendFoo({});
  const foo = await waitForFoo;
  assert_equals(foo.name, 'Fooby');
  assert_true(foo.a);
  assert_equals(foo.data, null);

  const waitForDefaults = new Promise(
      resolve => router.sendDefaultsTest.addListener(resolve));
  sender.sendDefaultsTest({
    a18: [],
    a19: '',
    a21: {x: 0, y: 0},
    a22: {location: {x: 0, y: 0}, size: {width: 0, height: 0}},
  });
  const defaults = await waitForDefaults;
  assert_equals(defaults.a0, -12);
  assert_equals(defaults.a1, TWELVE);
  assert_equals(defaults.a2, 1234);
  assert_equals(defaults.a3, 34567);
  assert_equals(defaults.a4, 123456);
  assert_equals(defaults.a5, 3456789012);
  assert_equals(defaults.a6, -111111111111n);
  assert_equals(defaults.a7, 9999999999999999999n);
  assert_equals(defaults.a8, 0x12345);
  assert_equals(defaults.a9, -0x12345);
  assert_equals(defaults.a10, 1234);
  assert_true(defaults.a11);
  assert_false(defaults.a12);
  assert_equals(defaults.a13, 123.25);
  assert_equals(defaults.a14, 1234567890.123);
  assert_equals(defaults.a15, 1E10);
  assert_equals(defaults.a16, -1.2E+20);
  assert_equals(defaults.a17, 1.23E-20);
  assert_equals(defaults.a20, Bar_Type.BOTH);
  assert_true(!!defaults.a22);
  assert_equals(defaults.a22.shape, Shape.RECTANGLE);
  assert_equals(defaults.a22.color, Color.BLACK);
  assert_equals(defaults.a23, 0xFFFFFFFFFFFFFFFFn);
  assert_equals(defaults.a24, 0x123456789n);
  assert_equals(defaults.a25, -0x123456789n);
}, 'default values');

promise_test(async () => {
  class ServiceImpl {
    frobinate(foo, baz, port) {
      checkFoo(foo);
      assert_equals(baz, Service_BazOptions.EXTRA);
      assert_true(port.$.isBound());
      return {result: 1234};
    }

    getPort(receiver) {}
  }

  const foo = makeFoo();
  checkFoo(foo);

  const service = new ServiceRemote();
  const receiver = new ServiceReceiver(new ServiceImpl());
  receiver.$.bindHandle(service.$.bindNewPipeAndPassReceiver().handle);

  const port = new PortRemote();
  port.$.bindNewPipeAndPassReceiver().handle.close();
  const {result} = await service.frobinate(foo, Service_BazOptions.EXTRA, port);
  assert_equals(result, 1234);
}, 'sample service');

function makeFoo() {
  const bar = {alpha: 20, beta: 40, gamma: 60, type: Bar_Type.VERTICAL};

  const extraBars = new Array(3);
  for (let i = 0; i < extraBars.length; ++i) {
    const base = i * 100;
    const type = i % 2 ? Bar_Type.VERTICAL : Bar_Type.HORIZONTAL;
    extraBars[i] = {alpha: base, beta: base + 20, gamma: base + 40, type: type};
  }

  const data = new Array(10);
  for (let i = 0; i < data.length; ++i) {
    data[i] = data.length - i;
  }

  return {
    name: 'foopy',
    x: 1,
    y: 2,
    a: false,
    b: true,
    c: false,
    bar: bar,
    extraBars: extraBars,
    data: data,
    source: Mojo.createMessagePipe().handle0,
  };
}

// Checks that the given |Foo| is identical to the one made by |makeFoo()|.
function checkFoo(foo) {
  assert_equals(foo.name, 'foopy');
  assert_equals(foo.x, 1);
  assert_equals(foo.y, 2);
  assert_false(foo.a);
  assert_true(foo.b);
  assert_false(foo.c);
  assert_equals(foo.bar.alpha, 20);
  assert_equals(foo.bar.beta, 40);
  assert_equals(foo.bar.gamma, 60);
  assert_equals(foo.bar.type, Bar_Type.VERTICAL);

  assert_equals(foo.extraBars.length, 3);
  for (var i = 0; i < foo.extraBars.length; ++i) {
    var base = i * 100;
    var type = i % 2 ?  Bar_Type.VERTICAL : Bar_Type.HORIZONTAL;
    assert_equals(foo.extraBars[i].alpha, base);
    assert_equals(foo.extraBars[i].beta, base + 20);
    assert_equals(foo.extraBars[i].gamma, base + 40);
    assert_equals(foo.extraBars[i].type, type);
  }

  assert_equals(foo.data.length, 10);
  for (var i = 0; i < foo.data.length; ++i)
    assert_equals(foo.data[i], foo.data.length -i);

  assert_true(foo.source instanceof MojoHandle);
}

</script>
